import React, {useRef, useState} from 'react';
import FunMemoOne from '@/components/15- 常用Hooks/03- memo/FunMemoOne.jsx'
import FunMemoTwo from '@/components/15- 常用Hooks/03- memo/FunMemoTwo.jsx'
import FunMemoThree from '@/components/15- 常用Hooks/03- memo/FunMemoThree.jsx'

function App(props) {

    /**
     * 高阶组件 memo（HOC）
     * 实际上是一个函数，用于优化函数组件的性能
     * 防止组件在其props没有变化时发生不必要的重新渲染(与类组件中的 PureComponent 类似)
     * 用法：
     * 接收一个组件作为参数，并返回一个新的组件 props的浅比较，如果props没有变化，则不会调用原始组件的渲染函数。
     * 解决：
     *  解决了当父组件render时，子组件未依赖父组件的数据,也会重新render,造成性能浪费
     */

    let [num, setNum] = useState(0);
    let [count, setCount] = useState(10);
    let [arrData, setArrData] = useState([1, 2, 3]);
    let [objData, setObjData] = useState({items: [1, 2, 3]});
    return (
        <div>
            <h2>APP 根组件</h2>
            <button onClick={() => {
                setNum(num += 1)
            }}>
                修改num {num}
            </button>
            <button onClick={() => {
                setCount(count += 1)
            }}>
                修改count {count}
            </button>
            <button onClick={() => {
                setArrData([...arrData, arrData.length + 1])
            }}>
                修改arrData {arrData}
            </button>
            <button onClick={() => {
                // // 直接修改数组内容，而不是创建新的数组引用
                // objData.items[0] = 42;
                // // 由于没有创建新的 objData 对象引用，React.memo 将不会检测到变化
                // setObjData(objData);// 实际上，这里的 setData 调用是多余的，因为 data 已经被直接修改了
                // console.log("objData", objData); // [42, 2, 3]
                // // 正确的做法应该是创建一个新的数组和对象引用，例如：
                // // setObjData({ ...objData, items: [42, ...objData.items.slice(1)] });

                setObjData({...objData, items: [42, ...objData.items.slice(1)]});
            }}>
                修改objData ==> {objData.items}
            </button>
            {/*
                此时修改任意状态,FunMemoOne组件都会重新渲染
            */}
            <FunMemoOne num={num} count={count} arrData={arrData}></FunMemoOne>
            {/*
                此时只有修改所依赖的num数据时,FunMemoTwo组件才会重新渲染
            */}
            <FunMemoTwo num={num}></FunMemoTwo>
            {/*
                直接修改数组内容,React.memo 没有检测到变化的情况(memo第二个参数 ==> 回调函数)
            */}
            <FunMemoThree objData={objData}></FunMemoThree>
        </div>
    );
}

export default App;